<template>
  <section class="mark-point-wrap">
    <el-card>
      <el-form :inline="true">
        <el-form-item label="楼栋：">
          <el-select class="point-filter-select" v-model="bNo" placeholder="请选择楼栋" @change="bNoChange">
            <el-option
              v-for="item in floorData"
              :key="item.buildingNo"
              :value="item.buildingNo"
              :label="item.buildingName"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="楼层：">
          <el-select class="point-filter-select" v-model="fNo" placeholder="请选择楼层" @change="fNoChange">
            <el-option
              v-for="item in nowFloorList"
              :key="item.floorNo"
              :value="item.floorNo"
              :label="item.floorName"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="宽度：">
          <el-input class="canvas-setup-input" v-model="inputWidth"></el-input>
        </el-form-item>
        <el-form-item label="高度：">
          <el-input class="canvas-setup-input" v-model="inputHeight"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="setSize">设置尺寸</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <el-card>
      <el-row type="flex" class="row-bg">
        <el-col :span="20">
          <div class="point-map">
            <canvas
              id="pointApp"
              :width="mapWidth"
              :height="mapHeight"
              @dragover="dotDragOver"
              @drop="dotDrop($event)"
            ></canvas>
          </div>
        </el-col>
        <el-col :span="4">
          <h3 class="device-list-title">设备列表</h3>
          <div class="device-list-filter">
            <el-checkbox class="filter-checkbox" v-model="curFloorDevice" @change="curDeviceTypeChange"
              >仅显示当前楼层设备</el-checkbox
            >
            <el-select v-model="nowDeviceType" multiple placeholder="请选择设备类型" @change="curDeviceTypeChange">
              <el-option v-for="item in deviceArr" :key="item.value" :label="item.label" :value="item.value">
              </el-option>
            </el-select>
          </div>
          <div class="device-list-wrap">
            <ul class="device-list">
              <li
                v-for="item in nowDotList"
                v-show="item.show"
                :key="item.deviceId"
                draggable="true"
                @mousemove="devicePopShow($event, item)"
                @mouseleave="devicePopHide"
                @dragstart="dotDragStart($event, item)"
                :style="item.pos && item.pos.fNo ? 'color: red' : ''"
              >
                {{ item.deviceName }}
                <template v-if="item.pos && item.pos.fNo">({{ item.pos.bNo }}, {{ item.pos.fNo }})</template>
              </li>
            </ul>
            <div
              class="device-list-pop"
              :style="'left:' + nowDevicePopData.left + ';top:' + nowDevicePopData.top"
              v-show="showDevicePop"
            >
              <p>设备id：{{ nowDevicePopData.deviceId }}</p>
              <p>设备名称：{{ nowDevicePopData.deviceName }}</p>
              <p>设备类型：{{ nowDevicePopData.deviceType }}</p>
            </div>
          </div>
        </el-col>
      </el-row>
      <el-row class="row-tips">
        <h5>使用小提示：</h5>
        <p>1.双击点位可进行点位位置信息删除操作。</p>
        <p>2.点位若拖出范围之外，会被弹回上一次的位置。</p>
        <p>3.保存设置会对所有楼层的设置进行保存，不会单保存一个楼层。</p>
        <p>
          4.<b style="color: red">请慎用尺寸变换功能</b
          >，使用尺寸变换功能后，室内地图会根据最新的尺寸进行变换，标记的点位会根据当前地图尺寸的变换进行等比的变换，但系统不会记录任何一次尺寸变换的记录，
          <br />所以建议在代码中配置初始尺寸信息。该功能建议使用场景为原先设计的室内地图已批量调整了大小，且不想重新进行标点，修改为切记将代码中的初始尺寸也修改为最新的尺寸。
          <br />尽量使用等比转换。
        </p>
      </el-row>
    </el-card>
    <el-card>
      <el-button type="primary" @click="saveSettings">保存设置</el-button>
    </el-card>
  </section>
</template>

<script>
import zrender from 'zrender'
import { floorData } from '@/views/children/dcenter/js/floor'
import { createBackground, dotTransfer } from '@/views/children/dcenter/js/canvas'
import deviceData from '@/mock/device'
const deviceArr = [
  { value: 1, label: '摄像机' },
  { value: 2, label: '烟感' },
  { value: 3, label: '门禁' },
  { value: 4, label: '地磁' }
]
export default {
  data () {
    return {
      deviceArr, // 设备类型列表（临时，需后端传入）
      nowDeviceType: [], // 当前选中的设备类型列表
      floorData, // 所有楼栋楼层数据
      showDevicePop: false, // 是否显示设备详情弹窗
      nowDevicePopData: {}, // 当前hover的设备详情
      isMap: false, // 画面上是否有地图
      mapIns: null, // 地图实例
      nowFloorList: [], // 当前楼栋楼层数据
      nowDotList: [], // 当前点位数据
      nowImg: '', // 当前选中楼层图片
      bNo: '', // 楼栋
      fNo: '', // 楼层
      mapWidth: 1000, // 楼层图片默认宽度
      mapHeight: 800, // 楼层图片默认高度
      inputWidth: 0, // 楼层图片设置宽度
      inputHeight: 0, // 楼层图片设置高度
      dotBgColor: [
        '#409EFF',
        '#c23531',
        '#2f4554',
        '#61a0a8',
        '#d48265',
        '#91c7ae',
        '#749f83',
        '#ca8622',
        '#bda29a',
        '#6e7074',
        '#546570',
        '#c4ccd3'
      ], // 点位背景颜色
      nowColorObj: {}, // 当前已经被选择过的颜色对象
      nowColorNum: 0, // 当前已经被选择过的颜色位置
      startPosition: {}, // dragStart时位置保存
      selectedDragItem: null, // 当前被拖拽中的设备
      isRepeat: false, // 是否重复的点
      curFloorDevice: false // 仅显示当前楼层，默认为否
    }
  },
  components: {},
  mounted () {
    this.inputWidth = this.mapWidth
    this.inputHeight = this.mapHeight
    // 获取所有设备数据
    this.nowDotList = [].concat(deviceData)
    // this.nowDotList.forEach(item => {
    //   item.show = true
    // })
    this.mapIns = zrender.init(document.getElementById('pointApp'))
  },
  methods: {
    // 楼栋切换
    bNoChange (val) {
      this.isMap = false
      let tempList = this.floorData.find(item => item.buildingNo === val)
      if (tempList.floorArr.length) {
        this.nowFloorList = tempList.floorArr
      }
      this.mapIns.clear()
      this.fNo = ''
    },
    // 楼层切换
    fNoChange () {
      this.isMap = true
      let temp = this.nowFloorList.find(item => item.floorNo === this.fNo)
      this.nowImg = temp.floorImg
      this.curDeviceTypeChange(this.curFloorDevice)
      // 切换后的处理
      this.mapIns.clear()
      this.mapIns.add(createBackground(this.nowImg, this.mapWidth, this.mapHeight))
      let tempList = this.getFloorDevice()
      tempList.forEach(item => {
        let newDot = this.createDot(item, item.pos.x, item.pos.y)
        this.mapIns.add(newDot)
      })
    },
    // 设置画布尺寸
    setSize () {
      if (this.mapWidth === this.inputWidth && this.mapHeight === this.inputHeight) {
        this.$message({
          type: 'info',
          message: '尺寸并未改变'
        })
        return
      }
      let lastWidth = this.mapWidth // 上次宽度
      let lastHeight = this.mapHeight // 上次高度
      this.$confirm('尺寸变换会导致所有已设置的点位信息进行对应的变换，请确定进行尺寸的变换?', '提示(请谨慎使用)', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          this.mapWidth = this.inputWidth || 0
          this.mapHeight = this.inputHeight || 0
          // 重新渲染地图
          this.nowDotList.forEach(item => {
            if (item.pos && item.pos.fNo) {
              let pos = dotTransfer(item.pos.x, item.pos.y, lastWidth, lastHeight, this.mapWidth, this.mapHeight)
              item.pos.x = pos.newX
              item.pos.y = pos.newY
            }
          })
          this.fNoChange()
          this.$message({
            type: 'info',
            message: '尺寸设置成功'
          })
        })
        .catch(() => {
          this.$message({
            type: 'info',
            message: '已取消尺寸设置'
          })
        })
    },
    // 找到某楼层所有设备
    getFloorDevice () {
      return this.nowDotList.filter(item => {
        return item.pos && item.pos.bNo === this.bNo && item.pos.fNo === this.fNo
      })
    },
    // 设备列表详情显示
    devicePopShow (e, item) {
      let temp = Object.assign({}, item)
      temp.left = e.clientX + 30 + 'px'
      temp.top = e.clientY - 25 + 'px'
      this.nowDevicePopData = temp
      this.showDevicePop = true
    },
    // 设备列表详情隐藏
    devicePopHide () {
      this.showDevicePop = false
    },
    // 点位拖拽开始
    dotDragStart (e, item) {
      // 是否地图上已有的点(包括其他楼层)
      // item.color = 'red'
      this.isRepeat = item.pos && item.pos.fNo // 有位置信息就代表是已有点位
      if (this.isRepeat) return
      if (!this.isMap) return
      this.selectedDragItem = item
    },
    // 点位拖拽
    dotDragOver (e) {
      if (this.isRepeat) return
      if (!this.isMap) return
      e.preventDefault()
    },
    // 点位结束
    dotDrop (e) {
      // e.offsetX,e.offsetY为在canvas中的坐标
      let newDot = this.createDot(this.selectedDragItem, e.offsetX, e.offsetY)
      this.mapIns.add(newDot)
    },
    // 设定背景颜色
    createDotColor (obj) {
      if (!this.nowColorObj[obj.deviceType]) {
        this.nowColorObj[obj.deviceType] = this.dotBgColor[this.nowColorNum]
        this.nowColorNum++
      }
      return this.nowColorObj[obj.deviceType]
    },
    // 插入点位的方法
    createDot (obj, x, y) {
      let dot = new zrender.Circle({
        zlevel: 0,
        draggable: true,
        style: {
          text: obj.deviceName[0], // 取第一个字
          fill: this.createDotColor(obj),
          textFill: '#fff'
        },
        shape: {
          cx: 0,
          cy: 0,
          r: 16
        },
        position: [x, y]
      })
      // 此处修改会直接影响nowDotList的值
      obj.pos = {}
      obj.pos.x = x
      obj.pos.y = y
      obj.pos.bNo = this.bNo
      obj.pos.fNo = this.fNo
      // this.nowDotList.push(obj)
      dot.on('dblclick', () => {
        this.$confirm('是否删除当前点位信息?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
          .then(() => {
            this.mapIns.remove(dot)
            this.nowDotList.forEach(item => {
              if (item.deviceId === obj.deviceId) {
                item.pos = {}
              }
            })
            this.$message({
              type: 'success',
              message: '删除成功!'
            })
            this.curDeviceTypeChange(this.curFloorDevice)
            this.$forceUpdate()
          })
          .catch(() => {
            this.$message({
              type: 'info',
              message: '已取消删除'
            })
          })
      })
      dot.on('mousemove', e => {
        this.dotPopShow(obj, e)
      })
      dot.on('mouseout', () => {
        this.dotPopHide()
      })
      dot.on('dragstart', e => {
        this.startPosition = { x: e.offsetX, y: e.offsetY }
        this.dotPopHide()
      })
      dot.on('drag', () => {
        this.dotPopHide()
      })
      dot.on('dragend', e => {
        if (e.offsetX > this.mapWidth - 16 || e.offsetY > this.mapHeight - 16 || e.offsetX < 0 || e.offsetY < 0) {
          dot.animateTo(
            {
              shape: {
                cx: 0,
                cy: 0,
                r: 16
              },
              position: [this.startPosition.x, this.startPosition.y]
            },
            0,
            0
          )
          this.$message({
            message: '拖动请勿超出范围，图标已移动至原先点位',
            type: 'warning'
          })
        } else {
          this.nowDotList.forEach(item => {
            if (item.deviceId === obj.deviceId) {
              dot.position = [e.offsetX, e.offsetY]
              item.pos.x = e.offsetX
              item.pos.y = e.offsetY
            }
          })
        }
      })
      return dot
    },
    // 点位详情显示
    dotPopShow (item, e) {
      let temp = Object.assign({}, item)
      temp.left = e.event.screenX + 30 + 'px'
      temp.top = e.event.screenY - 115 + 'px'
      this.nowDevicePopData = temp
      this.showDevicePop = true
    },
    // 点位详情隐藏
    dotPopHide () {
      this.showDevicePop = false
    },
    // 保存设置
    saveSettings () {
      console.log(this.nowDotList)
    },
    // 设备列表筛选
    curDeviceTypeChange () {
      if (this.curFloorDevice) {
        this.nowDotList.forEach(item => {
          item.show =
            item.pos &&
            item.pos.bNo === this.bNo &&
            item.pos.fNo === this.fNo &&
            this.nowDeviceType.indexOf(item.deviceType) > -1
        })
      } else {
        this.nowDotList.forEach(item => {
          item.show = this.nowDeviceType.indexOf(item.deviceType) > -1
        })
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.mark-point-wrap {
  width: 100%;
  padding: 15px;
  box-sizing: border-box;
  .point-map {
    width: 100%;
    height: 100%;
    overflow-x: scroll;
  }
  .device-list-title {
    font-size: 16px;
    text-align: center;
  }
  .device-list-filter {
    margin-top: 10px;
    .filter-checkbox {
      margin-bottom: 10px;
    }
  }
  .device-list-wrap {
    height: 700px;
    margin-top: 10px;
    border: 1px solid #ddd;
    overflow: auto;
    .device-list {
      height: 100%;
      padding: 15px;
      box-sizing: border-box;
      li {
        height: 32px;
        line-height: 32px;
        font-size: 14px;
        cursor: pointer;
        user-select: none;
        &:hover {
          color: #1890ff;
        }
      }
    }
  }
  .device-list-pop {
    position: fixed;
    min-width: 120px;
    padding: 15px;
    background-color: rgba(0, 0, 0, 0.8);
    border: 1px solid #ddd;
    border-radius: 10px;
    color: #fff;
  }
  .row-tips {
    margin-top: 20px;
    font-size: 14px;
    h5 {
      color: #ff4949;
    }
  }
}
</style>
